package cn.iocoder.yudao.module.ao.service.classlocation;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.module.ao.controller.admin.classlocation.vo.*;
import cn.iocoder.yudao.module.ao.dal.dataobject.classlocation.ClassLocationDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.ao.dal.mysql.classlocation.ClassLocationMapper;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.yudao.module.ao.enums.ErrorCodeConstants.*;

/**
 * 上课场地信息 Service 实现类
 *
 * @author 智教云枢
 */
@Slf4j
@Service
@Validated
public class ClassLocationServiceImpl implements ClassLocationService {

    @Resource
    private ClassLocationMapper classLocationMapper;

    @Override
    public Long createClassLocation(ClassLocationSaveReqVO createReqVO) {
        // 插入
        ClassLocationDO classLocation = BeanUtils.toBean(createReqVO, ClassLocationDO.class);
        classLocationMapper.insert(classLocation);

        // 返回
        return classLocation.getLocationId();
    }

    @Override
    public void updateClassLocation(ClassLocationSaveReqVO updateReqVO) {
        // 校验存在
        validateClassLocationExists(updateReqVO.getLocationId());
        // 更新
        ClassLocationDO updateObj = BeanUtils.toBean(updateReqVO, ClassLocationDO.class);
        classLocationMapper.updateById(updateObj);
    }

    @Override
    public void deleteClassLocation(Long id) {
        // 校验存在
        validateClassLocationExists(id);
        // 删除
        classLocationMapper.deleteById(id);
    }

    @Override
        public void deleteClassLocationListByIds(List<Long> ids) {
        // 删除
        classLocationMapper.deleteByIds(ids);
        }


    private void validateClassLocationExists(Long id) {
        if (classLocationMapper.selectById(id) == null) {
            throw exception(LOCATION_NOT_EXISTS);
        }
    }

    @Override
    public ClassLocationDO getClassLocation(Long id) {
        return classLocationMapper.selectById(id);
    }

    @Override
    public PageResult<ClassLocationDO> getClassLocationPage(ClassLocationPageReqVO pageReqVO) {
        return classLocationMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ClassLocationImportRespVO importClassLocationList(List<ClassLocationImportExcelVO> importClassLocations, Boolean updateSupport) {
        if (CollUtil.isEmpty(importClassLocations)) {
            throw exception(LOCATION_IMPORT_LIST_IS_EMPTY);
        }

        log.info("开始处理场地导入，总数: {}, 支持更新: {}", importClassLocations.size(), updateSupport);

        ClassLocationImportRespVO respVO = ClassLocationImportRespVO.builder()
                .createClassLocationCount(0).updateClassLocationCount(0).failureClassLocationCount(0)
                .failureClassLocationMessages(new ArrayList<>()).build();

        for (int i = 0; i < importClassLocations.size(); i++) {
            ClassLocationImportExcelVO importClassLocation = importClassLocations.get(i);
            int rowNumber = i + 1;
            try {
                log.info("🔄 处理第 {} 行: 场地={}, 楼名={}, 楼层={}, 容量={}",
                        rowNumber,
                        importClassLocation.getLocationName(),
                        importClassLocation.getBuildingName(),
                        importClassLocation.getFloor(),
                        importClassLocation.getClassroomCapacity());

                // 数据验证
                if (StrUtil.isBlank(importClassLocation.getLocationName())) {
                    respVO.setFailureClassLocationCount(respVO.getFailureClassLocationCount() + 1);
                    respVO.getFailureClassLocationMessages().add(String.format("第 %d 行：场地名称不能为空", rowNumber));
                    continue;
                }

                // 转换为DO对象
                ClassLocationDO classLocation = convertToClassLocationDO(importClassLocation);

                // 检查是否已存在相同名称+建筑物的场地 - 使用精确匹配
                List<ClassLocationDO> existingLocations = classLocationMapper.selectList(
                        new LambdaQueryWrapperX<ClassLocationDO>()
                                .eq(ClassLocationDO::getLocationName, importClassLocation.getLocationName().trim())
                                .eq(ClassLocationDO::getBuildingId, classLocation.getBuildingId())
                );

                log.info("检查场地是否存在: {} (建筑物ID: {}) -> 找到 {} 条记录",
                        importClassLocation.getLocationName(),
                        classLocation.getBuildingId(),
                        existingLocations.size());

                if (!existingLocations.isEmpty() && !updateSupport) {
                    respVO.setFailureClassLocationCount(respVO.getFailureClassLocationCount() + 1);
                    respVO.getFailureClassLocationMessages().add(String.format("第 %d 行：场地名称 '%s' 已存在",
                        rowNumber, importClassLocation.getLocationName()));
                    continue;
                }

                if (!existingLocations.isEmpty() && updateSupport) {
                    // 更新现有记录 - 只更新Excel中提供的非空字段
                    ClassLocationDO existingLocation = existingLocations.get(0);
                    log.info("✅ 进入更新逻辑 - 场地: {}, ID: {}, updateSupport: {}",
                            importClassLocation.getLocationName(),
                            existingLocation.getLocationId(),
                            updateSupport);
                    updateExistingLocation(existingLocation, importClassLocation);
                    classLocationMapper.updateById(existingLocation);
                    respVO.setUpdateClassLocationCount(respVO.getUpdateClassLocationCount() + 1);
                    log.info("✅ 更新完成 - 场地: {}", importClassLocation.getLocationName());
                } else if (!existingLocations.isEmpty() && !updateSupport) {
                    log.info("❌ 跳过更新 - 场地: {}, 原因: updateSupport=false", importClassLocation.getLocationName());
                } else {
                    // 创建新记录
                    log.info("创建新场地记录: 名称={}, 建筑物ID={}, 楼层={}, 容量={}",
                            classLocation.getLocationName(),
                            classLocation.getBuildingId(),
                            classLocation.getFloor(),
                            classLocation.getClassroomCapacity());
                    classLocationMapper.insert(classLocation);
                    respVO.setCreateClassLocationCount(respVO.getCreateClassLocationCount() + 1);
                }

            } catch (Exception e) {
                respVO.setFailureClassLocationCount(respVO.getFailureClassLocationCount() + 1);
                String errorMsg = String.format("第 %d 行：%s",
                        importClassLocations.indexOf(importClassLocation) + 1, e.getMessage());
                respVO.getFailureClassLocationMessages().add(errorMsg);
                log.error("❌ 导入失败: 场地={}, 错误={}", importClassLocation.getLocationName(), errorMsg, e);
            }
        }

        log.info("导入完成 - 创建: {}, 更新: {}, 失败: {}",
                respVO.getCreateClassLocationCount(),
                respVO.getUpdateClassLocationCount(),
                respVO.getFailureClassLocationCount());

        return respVO;
    }

    /**
     * 将导入Excel VO转换为DO对象
     */
    private ClassLocationDO convertToClassLocationDO(ClassLocationImportExcelVO importVO) {
        ClassLocationDO classLocation = new ClassLocationDO();

        // 根据楼名设置建筑物ID
        Long buildingId = getBuildingIdByName(importVO.getBuildingName());
        if (buildingId == null) {
            throw new IllegalArgumentException("无法识别的楼名: " + importVO.getBuildingName());
        }
        classLocation.setBuildingId(buildingId);

        // 保持场地名称为纯数字格式，与中高技班级课管理模块的标准化策略一致
        String locationName = importVO.getLocationName().trim();
        if (StrUtil.isBlank(locationName)) {
            throw new IllegalArgumentException("场地名称不能为空");
        }
        classLocation.setLocationName(locationName);

        // 验证楼层
        if (importVO.getFloor() == null || importVO.getFloor() < 1) {
            throw new IllegalArgumentException("楼层必须是正整数");
        }
        classLocation.setFloor(importVO.getFloor());

        // 验证容量
        if (importVO.getClassroomCapacity() == null || importVO.getClassroomCapacity() < 1) {
            throw new IllegalArgumentException("教室容量必须是正整数");
        }
        classLocation.setClassroomCapacity(importVO.getClassroomCapacity());

        // 设置默认值
        classLocation.setLocationType("教室"); // 默认类型
        classLocation.setStatus(1); // 默认启用状态

        log.debug("转换完成: 场地={}, 建筑物ID={}, 楼层={}, 容量={}",
                locationName, buildingId, importVO.getFloor(), importVO.getClassroomCapacity());

        return classLocation;
    }

    /**
     * 处理场地名称：如果是纯数字，根据建筑物ID添加前缀
     * @param locationName 原始场地名称
     * @param buildingId 建筑物ID
     * @return 处理后的场地名称
     */
    private String processLocationName(String locationName, Long buildingId) {
        if (StrUtil.isBlank(locationName)) {
            return locationName;
        }

        String trimmedName = locationName.trim();

        // 检查是否为纯数字
        if (trimmedName.matches("\\d+")) {
            // 根据建筑物ID添加前缀
            if (buildingId != null) {
                if (buildingId.equals(1L)) {
                    // 笃志楼：添加前缀 "D"
                    String processedName = "D" + trimmedName;
                    log.info("场地名称处理: {} -> {} (建筑物ID: 1-笃志楼)", trimmedName, processedName);
                    return processedName;
                } else if (buildingId.equals(2L)) {
                    // 博学楼：添加前缀 "B"
                    String processedName = "B" + trimmedName;
                    log.info("场地名称处理: {} -> {} (建筑物ID: 2-博学楼)", trimmedName, processedName);
                    return processedName;
                } else {
                    log.debug("未知建筑物ID: {}，场地名称保持不变: {}", buildingId, trimmedName);
                }
            } else {
                log.debug("建筑物ID为空，纯数字场地名称保持不变: {}", trimmedName);
            }
        }

        // 非纯数字或无法处理的情况，返回原始名称
        return trimmedName;
    }

    /**
     * 根据楼名获取建筑物ID
     * @param buildingName 楼名
     * @return 建筑物ID
     */
    private Long getBuildingIdByName(String buildingName) {
        if (StrUtil.isBlank(buildingName)) {
            return null;
        }

        // 根据楼名映射建筑物ID
        switch (buildingName.trim()) {
            case "笃志楼":
                return 1L;
            case "博学楼":
                return 2L;
            default:
                // 如果是未知楼名，记录日志并返回null
                log.warn("未知的楼名: {}", buildingName);
                return null;
        }
    }

    /**
     * 更新现有场地信息 - 只更新Excel中提供的非空字段
     */
    void updateExistingLocation(ClassLocationDO existingLocation, ClassLocationImportExcelVO importVO) {
        log.info("更新前数据: ID={}, 名称={}, 建筑物ID={}, 楼层={}, 容量={}",
                existingLocation.getLocationId(),
                existingLocation.getLocationName(),
                existingLocation.getBuildingId(),
                existingLocation.getFloor(),
                existingLocation.getClassroomCapacity());

        log.info("Excel数据: 名称={}, 楼名={}, 楼层={}, 容量={}",
                importVO.getLocationName(),
                importVO.getBuildingName(),
                importVO.getFloor(),
                importVO.getClassroomCapacity());

        // 建筑物ID - 如果Excel中提供了楼名，则更新建筑物ID
        Long buildingId = existingLocation.getBuildingId(); // 保持原有建筑物ID
        if (StrUtil.isNotBlank(importVO.getBuildingName())) {
            Long newBuildingId = getBuildingIdByName(importVO.getBuildingName());
            if (newBuildingId != null) {
                buildingId = newBuildingId;
                existingLocation.setBuildingId(buildingId);
                log.info("更新建筑物ID: {} -> {}", existingLocation.getBuildingId(), buildingId);
            }
        }

        // 场地名称（必填字段，已经验证过非空）- 保持纯数字格式
        String oldName = existingLocation.getLocationName();
        existingLocation.setLocationName(importVO.getLocationName().trim());
        log.info("更新场地名称: {} -> {}", oldName, existingLocation.getLocationName());

        // 楼层信息 - 如果Excel中提供了楼层信息，则更新
        if (importVO.getFloor() != null) {
            Integer oldFloor = existingLocation.getFloor();
            existingLocation.setFloor(importVO.getFloor());
            log.info("更新楼层: {} -> {}", oldFloor, existingLocation.getFloor());
        }

        // 教室容量 - 如果Excel中提供了容量信息，则更新
        if (importVO.getClassroomCapacity() != null) {
            Integer oldCapacity = existingLocation.getClassroomCapacity();
            existingLocation.setClassroomCapacity(importVO.getClassroomCapacity());
            log.info("更新容量: {} -> {}", oldCapacity, existingLocation.getClassroomCapacity());
        }

        log.info("更新后数据: ID={}, 名称={}, 建筑物ID={}, 楼层={}, 容量={}",
                existingLocation.getLocationId(),
                existingLocation.getLocationName(),
                existingLocation.getBuildingId(),
                existingLocation.getFloor(),
                existingLocation.getClassroomCapacity());

        // 更新时间会由MyBatis Plus自动处理
    }

}